<template>
  <div class="cascade-main">
    <div>
      <div class="item-box" v-for="item in treeOptions" :key="item.key">
        <input
          type="radio"
          :name="`tree-item${id}`"
          :id="`${item.key}`"
          hidden
          :checked="item.key === expandedKeys[id]"
        />
        <label :for="`${item.key}`" class="title title-menu" @click="toggle(item)">
          <p>{{ item.label }}</p>
          <div class="icon-triangle" v-if="item.isFolder"></div>
        </label>
      </div>
    </div>

    <CascaderTree
      @click-item="emit('clickItem', $event)"
      @expand="emit('expand', $event)"
      v-model="treeValue"
      v-model:expanded-keys="childExpandedKeys"
      v-bind:expandeds="childExpandeds"
      :id="id + 1"
      :tree-options="child"
      v-if="child.length && reloadFolder"
    />
  </div>
</template>

<script setup lang="ts">
export interface TreeOption {
  key: number | string
  label: string
  isFolder?: boolean
  children?: Array<TreeOption>
}

interface Props {
  treeOptions: Array<TreeOption>
  modelValue?: string | number | undefined
  expandedKeys?: Array<string | number>
  expandeds?: Array<TreeOption>
  id?: number
}

const props = withDefaults(defineProps<Props>(), {
  treeOptions: () => [],
  expandedKeys: () => [],
  expandeds: () => [],
  id: 0
})

const emit = defineEmits(['update:modelValue', 'update:expandedKeys', 'clickItem', 'expand'])

const treeValue = computed({
  get() {
    return props.modelValue
  },
  set(value) {
    emit('update:modelValue', value)
  }
})

const childExpandedKeys = ref<Array<string | number>>(props.expandedKeys)
const childExpandeds = ref<Array<TreeOption>>(props.expandeds)
const child = ref<Array<TreeOption>>([])
const reloadFolder = ref(true)

watch(
  () => props.treeOptions,
  () => {
    reloadFolder.value = false
  }
)

onMounted(() => {
  props.treeOptions.forEach((item) => {
    if (item?.children?.length) {
      item.isFolder = true

      if (props.expandedKeys.includes(item.key)) {
        child.value = item.children

        childExpandeds.value[props.id] = item
        childExpandedKeys.value[props.id] = item.key
      }
    }
  })
})

const expandHandler = (item: TreeOption) => {
  childExpandeds.value.splice(props.id + 1)
  childExpandeds.value[props.id] = item
  childExpandedKeys.value.splice(props.id + 1)
  childExpandedKeys.value[props.id] = item.key

  emit('update:expandedKeys', childExpandedKeys.value)
  emit('expand', childExpandedKeys.value)
}

const toggle = (item: TreeOption) => {
  expandHandler(item)

  if (item.isFolder) {
    child.value = []
    nextTick(() => {
      child.value = item.children || []
    })
  } else {
    treeValue.value = item.key
    child.value = []
    emit('clickItem', { item, expandeds: childExpandeds.value })
  }
}
</script>

<style scoped lang="scss">
.cascade-main {
  display: flex;
  $tree-item-height: 30px;
  $tree-transition-duration: 0.4s;

  .item-box {
    color: #242527;
    font-size: 14px;
    position: relative;

    .title {
      display: flex;
      justify-content: center;
      align-items: center;
      height: $tree-item-height;
      transition: $tree-transition-duration;
      overflow: hidden;
      white-space: no-wrap;
      text-overflow: ellipsis;
      position: relative;
      cursor: pointer;
      width: 120px;
      min-width: 120px;
      max-height: 120px;

      &::before {
        content: '';
        position: absolute;
        height: 90%;
        width: calc(100% - 12px);
        margin: 0 6px;
        border-radius: 3px;
        transition: $tree-transition-duration;
        z-index: -1;
      }

      .icon-triangle {
        width: 6px;
        height: 6px;
        border-top: 3px solid transparent;
        border-left: 3px solid transparent;
        border-right: 3px solid #242527;
        border-bottom: 3px solid #242527;
        margin-right: 20px;
        transform: rotate(-45deg);
        position: absolute;
        right: 0;
      }

      p {
        padding: 4px;
        border-radius: 3px;
        transition: $tree-transition-duration;
        padding-left: 12px;
        width: 80%;
        overflow: hidden;
        white-space: no-wrap;
        text-overflow: ellipsis;
      }
    }

    .title-menu {
      &:hover::before {
        background-color: lighten($main-color, 25%);
      }
    }

    input[type='radio']:checked + .title-menu::before {
      background-color: lighten($main-color, 25%) !important;
    }
  }
}
</style>
